/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.sys.web;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;

import com.thinkgem.jeesite.common.utils.excel.ExportExcel;
import com.thinkgem.jeesite.common.utils.excel.ImportExcel;
import com.thinkgem.jeesite.modules.sys.entity.Area;
import com.thinkgem.jeesite.modules.sys.entity.OfficeImp;
import com.vivo.Utils.CommonUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.sys.entity.Office;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.OfficeService;
import com.thinkgem.jeesite.modules.sys.utils.DictUtils;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;

/**
 * 机构Controller
 * @author ThinkGem
 * @version 2013-5-15
 */
@Controller
@RequestMapping(value = "${adminPath}/sys/office")
public class OfficeController extends BaseController {

	@Autowired
	private OfficeService officeService;
	
	@ModelAttribute("office")
	public Office get(@RequestParam(required=false) String id) {
		if (StringUtils.isNotBlank(id)){
			return officeService.get(id);
		}else{
			return new Office();
		}
	}

	@RequiresPermissions("sys:office:view")
	@RequestMapping(value = {""})
	public String index(Office office, Model model) {
//        model.addAttribute("list", officeService.findAll());
        Office comp = UserUtils.getUser().getCompany();
        model.addAttribute("comp", comp);
		return "modules/sys/officeIndex";
	}

	@RequiresPermissions("sys:office:view")
	@RequestMapping(value = {"list"})
	public String list(Office office, Model model) {
        model.addAttribute("list", officeService.findList(office));
		return "modules/sys/officeList";
	}
	
	@RequiresPermissions("sys:office:view")
	@RequestMapping(value = "form")
	public String form(Office office, Model model) {
		User user = UserUtils.getUser();
		if (office.getParent()==null || office.getParent().getId()==null){
			office.setParent(user.getOffice());
		}

		Office parent = officeService.get(office.getParent().getId());

		office.setParent(parent);
		office.setArea(parent.getArea());
//		if (office.getArea()==null){
//			office.setArea(user.getOffice().getArea());
//		}
		// 自动获取排序号
		if (StringUtils.isBlank(office.getId())&&office.getParent()!=null){
//			int size = 0;
//			List<Office> list = officeService.findAll();
//			for (int i=0; i<list.size(); i++){
//				Office e = list.get(i);
//				if (e.getParent()!=null && e.getParent().getId()!=null
//						&& e.getParent().getId().equals(office.getParent().getId())){
//					size++;
//				}
//			}
//			office.setCode(office.getParent().getCode() + StringUtils.leftPad(String.valueOf(size > 0 ? size+1 : 1), 2, "0"));

            // 查看是否有其他子
            Office ot = new Office();
            ot.setParent(parent);
            ot.setGrade(String.valueOf(parent.getCode().length() + 2));

            ot = officeService.getByCodeLength(ot);
            if (ot == null) {
                office.setCode(CommonUtils.getNewCode(parent.getCode()));
            } else {
                office.setCode(CommonUtils.getNextCode(ot.getCode()));
            }
//			office.setCode();
		}
		model.addAttribute("office", office);
		return "modules/sys/officeForm";
	}
	
	@RequiresPermissions("sys:office:edit")
	@RequestMapping(value = "save")
	public String save(Office office, Model model, RedirectAttributes redirectAttributes) {
		if(Global.isDemoMode()){
			addMessage(redirectAttributes, "演示模式，不允许操作！");
			return "redirect:" + adminPath + "/sys/office/";
		}
		if (!beanValidator(model, office)){
			return form(office, model);
		}
		officeService.save(office);
		
		if(office.getChildDeptList()!=null){
			Office childOffice = null;
			for(String id : office.getChildDeptList()){
				childOffice = new Office();
				childOffice.setName(DictUtils.getDictLabel(id, "sys_office_common", "未知"));
				childOffice.setParent(office);
				childOffice.setArea(office.getArea());
				childOffice.setType("2");
				childOffice.setGrade(String.valueOf(Integer.valueOf(office.getGrade())+1));
				childOffice.setUseable(Global.YES);
				officeService.save(childOffice);
			}
		}
		
		addMessage(redirectAttributes, "保存机构'" + office.getName() + "'成功");
		String id = "0".equals(office.getParentId()) ? "" : office.getParentId();
		return "redirect:" + adminPath + "/sys/office/list?id="+id+"&parentIds="+office.getParentIds();
//        return "redirect:" + adminPath + "/sys/office/list?id="+id+"&parentIds="+office.getParentIds();
//        return "modules/sys/officeIndex";
	}
	
	@RequiresPermissions("sys:office:edit")
	@RequestMapping(value = "delete")
	public String delete(Office office, RedirectAttributes redirectAttributes) {
		if(Global.isDemoMode()){
			addMessage(redirectAttributes, "演示模式，不允许操作！");
			return "redirect:" + adminPath + "/sys/office/list";
		}
//		if (Office.isRoot(id)){
//			addMessage(redirectAttributes, "删除机构失败, 不允许删除顶级机构或编号空");
//		}else{
			officeService.delete(office);
			addMessage(redirectAttributes, "删除机构成功");
//		}
		return "redirect:" + adminPath + "/sys/office/list?id="+office.getParentId()+"&parentIds="+office.getParentIds();
	}

    /**
     * 导入Excel数据

     */
    @RequiresPermissions("sys:office:edit")
    @RequestMapping(value = "import", method= RequestMethod.POST)
    public String importFile(MultipartFile file, RedirectAttributes redirectAttributes) {
        if(!UserUtils.getUser().isAdmin()){
            addMessage(redirectAttributes, "越权操作，只有超级管理员才能修改此数据！");
            return "redirect:" + adminPath + "/sys/office/?repage";
        }

        try {
            int successNum = 0;
            int failureNum = 0;
            StringBuilder failureMsg = new StringBuilder();
            ImportExcel ei = new ImportExcel(file, 1, 0);
            List<OfficeImp> list = ei.getDataList(OfficeImp.class);
            for (OfficeImp oi : list){
                System.out.println(oi.getLevel1());
                try{
                    if (oi.getLevel1() == null || oi.getLevel1().equals("")) {
                        failureNum++;
                        continue;
                    }

                    String []comps = oi.getLevel1().split("-");
                    Office lastOffice = null;

                    // company type
                    String type = "1";
                    for (String compName : comps) {
                        lastOffice = createNewOffice(lastOffice, type, compName);

                        if (lastOffice == null) {
                            break;
                        }
                    }

                    if (oi.getLevel2() == null || oi.getLevel2().equals("")) {
                        continue;
                    }

                    String []depts = oi.getLevel2().split("-");
                    type = "2";
                    for(String deptName : depts) {
                        lastOffice = createNewOffice(lastOffice, type, deptName);
                        if (lastOffice == null) {
                            break;
                        }
                    }

                    if (oi.getLevel3() == null || oi.getLevel3().equals("")) {
                        continue;
                    }

                    String []posts = oi.getLevel3().split("-");
                    type = "3";
                    for(String postName : posts) {
                        lastOffice = createNewOffice(lastOffice, type, postName);
                        if (lastOffice == null) {
                            break;
                        }
                    }

                    successNum++;
                }catch(ConstraintViolationException ex){
                    failureNum++;
                }catch (Exception ex) {
                    ex.printStackTrace();
                    failureNum++;
                }
            }
            if (failureNum>0){
                failureMsg.insert(0, "，失败 "+failureNum+" 条组织机构记录。");
            }
            addMessage(redirectAttributes, "已成功导入 "+successNum+" 条组织机构记录"+failureMsg);
        } catch (Exception e) {
            addMessage(redirectAttributes, "导入组织机构失败！失败信息："+e.getMessage());
        }
//        return "redirect:"+Global.getAdminPath()+"/employee/viEmpTarget/?repage";

        return "redirect:" + adminPath + "/sys/office/?repage";
    }


    public Office createNewOffice(Office lastO, String type, String officeName) {
        Office curO = new Office();
        curO.setName(officeName);
        curO.setParent(lastO);
        curO.setType(type);

        curO = officeService.getOffice(curO);

        if (curO == null) {
            if (lastO == null) {

                Area area = new Area();
                area.setId("9c4b200a10b94fd7a2ace329e45e9bf8");
                // 创建一级部门
                curO = new Office();
                curO.setName(officeName);
                curO.setParent(null);
                curO.setType(type);
                curO.setGrade(type);
                curO.setCompanyKind(type);
                curO.setUseable("1");
                curO.setIsOld("0");
                curO.setSort(30);
                curO.setArea(area);

                if (officeName.equals("安徽区域")) {
                    curO.setCode("01");
                } else if (officeName.equals("江苏区域")) {
                    curO.setCode("02");
                } else {
                    curO.setCode("04");
                }



                officeService.save(curO);

                return curO;
            }

            // 创建新部门
            Office ot = new Office();
            ot.setParent(lastO);
            ot.setGrade(String.valueOf(lastO.getCode().length() + 2));

            ot = officeService.getByCodeLength(ot);

            curO = new Office();

            if (ot == null) {
                curO.setCode(CommonUtils.getNewCode(lastO.getCode()));
            } else {
                curO.setCode(CommonUtils.getNextCode(ot.getCode()));
            }
            curO.setName(officeName);
            curO.setParent(lastO);
            curO.setType(type);
            curO.setGrade(type);
            curO.setCompanyKind(type);
            curO.setUseable("1");
            curO.setIsOld("0");
            curO.setSort(30);
            curO.setArea(lastO.getArea());

            officeService.save(curO);
        } else {
            // 更新删除的信息
            if (curO.getDelFlag().equals("1")) {
                curO.setDelFlag("0");
                officeService.save(curO);
            }
        }
        return curO;
    }



    /**
     * 下载导入{functionNameSimple}数据模板
     */
    @RequiresPermissions("sys:office:edit")
    @RequestMapping(value = "import/template")
    public String importFileTemplate(HttpServletResponse response, RedirectAttributes redirectAttributes) {
        try {
            String fileName = "组织机构导入模板.xlsx";
            List<OfficeImp> list = Lists.newArrayList();
            new ExportExcel("组织机构数据", OfficeImp.class, 2).setDataList(list).write(response, fileName).dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "导入模板下载失败！失败信息："+e.getMessage());
        }
//        return "redirect:"+Global.getAdminPath()+"/employee/viEmpTarget/?repage";
        return "redirect:" + adminPath + "/sys/office/?repage";
    }





	/**
	 * 获取机构JSON数据。
	 * @param extId 排除的ID
	 * @param type	类型（1：公司；2：部门/小组/其它：3：用户）
	 * @param grade 显示级别
	 * @param response
	 * @return
	 */
	@RequiresPermissions("user")
	@ResponseBody
	@RequestMapping(value = "treeData")
	public List<Map<String, Object>> treeData(@RequestParam(required=false) String extId, @RequestParam(required=false) String type,
			@RequestParam(required=false) Long grade, @RequestParam(required=false) Boolean isAll,@RequestParam(required = false) Boolean hasCount, HttpServletResponse response) {
		List<Map<String, Object>> mapList = Lists.newArrayList();
		List<Office> list = officeService.findList(isAll);
		for (int i=0; i<list.size(); i++){
			Office e = list.get(i);
			if ((StringUtils.isBlank(extId) || (extId!=null && !extId.equals(e.getId()) && e.getParentIds().indexOf(","+extId+",")==-1))
					&& (type == null || (type != null && (type.equals("1") ? type.equals(e.getType()) : true)))
					&& (
					        grade == null ||
                                    (grade != null && Integer.parseInt(e.getGrade()) <= grade.intValue()
                                    ))
					&& Global.YES.equals(e.getUseable())){
				Map<String, Object> map = Maps.newHashMap();
				map.put("id", e.getId());
				map.put("pId", e.getParentId());
				map.put("pIds", e.getParentIds());
                map.put("name", e.getName());
				if (hasCount != null && hasCount && e.getEmpCount() != null) {
                    map.put("name", e.getName() + " (" + e.getEmpCount() + ")");
                }

				map.put("type", e.getType());
				if (type != null && "3".equals(type)){
					map.put("isParent", true);
				}
				mapList.add(map);
			}
		}
		return mapList;
	}

    @ResponseBody
    @RequestMapping(value = "ajaxData")
    public List<Map<String, Object>> treeData(@RequestParam(required=false) String type, @RequestParam(required=false) String name,
                                              @RequestParam(required = false, defaultValue = "false") Boolean hasCount,
                                              @RequestParam(required = false, defaultValue = "false") Boolean isWp) {
	    Office o = new Office();
	    o.setType(type);
	    o.setName(name);

	    if (!isWp) {
            Office p = new Office();
            p.setId(UserUtils.getUser().getCompany().getId());
            o.setParent(p);
        }

	    Map<String, Office> tempList = new HashMap<String, Office>();

        List<Map<String, Object>> mapList = Lists.newArrayList();
        List<Office> list = officeService.findListByTypeAndName(o);

        for(Office e : list) {
            Map<String, Object> map = Maps.newHashMap();

            map.put("id", e.getId());

            Office tempO = new Office();

            // TODO 获取部门节点
            String pCode = e.getCode().substring(0, 6);
            System.out.println("parent code is:" + pCode);

            tempO.setArea(e.getArea());
            tempO.setCode(pCode);
            tempO.setType("2");

            Office dept = tempList.get(pCode + e.getArea().getId());
            if (dept == null){
                dept = officeService.getOfficeByCode(tempO);
                if (dept == null) {
                    System.out.println("can not find p with: " + pCode);
                    continue;
                }
                tempList.put(pCode + e.getArea().getId(), dept);
            }

            // TODO 获取机构节点
            String ppCode = e.getCode().substring(0, 4);
            System.out.println("pp code is:" + ppCode);

            tempO.setArea(e.getArea());
            tempO.setCode(ppCode);
            tempO.setType("1");

            Office comp = tempList.get(ppCode + e.getArea().getId());
            if (comp == null){
                comp = officeService.getOfficeByCode(tempO);
                if (comp == null) {
                    System.out.println("can not find pp with: " + ppCode);
                    continue;
                }
                tempList.put(ppCode + e.getArea().getId(), comp);
            }

            map.put("ppId", comp.getId());
            map.put("ppName", comp.getName());

            map.put("pId", dept.getId());
            map.put("pName", dept.getName());

            map.put("name", e.getName());
            if (hasCount) {
                map.put("name", e.getName() + "(" + e.getEmpCount() + ")");
            }

            map.put("type", e.getType());

            mapList.add(map);
        }

        return mapList;
    }
}
